Data_for_d3

Author

Olaf König

1 Libraries

Code
libs <- c(
    "tidyverse", "tidylog", "sf", "transformr",
    "tweenr", "particles", "igraph",
    "tidygraph", "stringr", "hrbrthemes", "magick",
    "ggbeeswarm", "plotly", "rmapshaper", "mapview",
    "geojsonio"
)

# install missing libraries
installed_libs <- libs %in% rownames(installed.packages())
if (any(installed_libs == F)) {
    install.packages(libs[!installed_libs])
}

# load libraries
invisible(lapply(libs, library, character.only = T))

2 Data import

2.0.1 Spatial division

Code
spatial_division <- read_csv("data_input/spatial_division_2024_03_01.csv")

cols_to_check <- spatial_division %>% 
  select(HR_AGGL2012:HR_STADTE2020_Name_fr) %>% 
  names()

spatial_division_urbain_rural <- spatial_division %>%
  select(CODE_OFS,
         HR_GDETYP2012_L1,
         HR_GDETYP2012_L1_Name_fr,
         HR_GDETYP2012_L2,
         HR_GDETYP2012_L2_Name_fr,
         HR_SPRGEB2020, 
         HR_SPRGEB2020_Name_fr
         ) %>% 
  mutate(HR_GDETYP2012_L1_Name_fr = if_else(
    HR_GDETYP2012_L1_Name_fr == "Intermédiaire (périurbain dense et centres ruraux)",
    "Intermédiaire",
    HR_GDETYP2012_L1_Name_fr
  ))


# FACTORISATION
ordre_levels_GDETYP2012_L1 <- c(
  "Urbain",
  "Intermédiaire",
  "Rural"
)

# Facteurs 9 Types
ordre_levels_GDETYP2012_L2 <- c(
  "Commune urbaine d’une grande agglomération", 
  "Commune urbaine d'une agglomération moyenne", 
  "Commune urbaine d’une petite ou hors agglomération", 
  "Commune périurbaine de forte densité", 
  "Commune périurbaine de moyenne densité", 
  "Commune périurbaine de faible densité", 
  "Commune d’un centre rural", 
  "Commune rurale en situation centrale", 
  "Commune rurale périphérique"
)

spatial_division_urbain_rural <- spatial_division_urbain_rural %>% 
  mutate(
        # Factoriser la colonne HR_GDETYP2012_L1_Name_fr
    HR_GDETYP2012_L1_Name_fr = factor(HR_GDETYP2012_L1_Name_fr, 
                                      levels = ordre_levels_GDETYP2012_L1, 
                                      ordered = TRUE),
    
    # Factoriser la colonne HR_GDETYP2012_L2_Name_fr
    HR_GDETYP2012_L2_Name_fr = factor(HR_GDETYP2012_L2_Name_fr, 
                                      levels = ordre_levels_GDETYP2012_L2, 
                                      ordered = TRUE)
  )

2.1 Données politiques - toutes les votations

Code
# Data import
results <- read_rds("data_input/results_all.rds")

# Sélection des données des communes
municipalities_results <- lapply(results, function(x) x$df_municipalities)
municipalities_results_df <- bind_rows(municipalities_results) %>% 
  mutate(id = as.numeric(id)) %>% 
  left_join(spatial_division_urbain_rural, by = c("id" = "CODE_OFS"))

2.1.1 Données politiques - Initiative populaire «Pour une Suisse libre de pesticides de synthèse»

Code
pesticides_df <- municipalities_results_df %>% 
  filter(ballot_id == 6420) %>% 
  select(
    id, yes_pct, valid_votes
  ) %>% 
  rename(
    GMDNR = id
  )

2.1.2 Geodata

Code
# Communes
polg_sf <- read_sf("data_input/g1g24.gpkg") %>% 
  select(GMDNR, GMDNAME) %>%
  mutate(
    entity = "COMMUNE"
  ) %>% 
  st_transform(2056)

# Lacs
lake_sf <- read_sf("data_input/g1s24.gpkg") %>% 
  select(GMDNR, GMDNAME) %>% 
  mutate(
    entity = "LAKE"
  ) %>% 
  st_transform(2056)

# Assemblage
geodata_sf <- rbind(polg_sf, lake_sf)

2.1.3 Process Geodata (simplification, ajout des divisions spaciales)

Code
# Généralisation de la géométrie
geodata_simplify_sf <- ms_simplify(geodata_sf, keep = 0.1, method = "vis")

# Ajout des attributs de divisions spatiales
geodata_simplify_sf <- geodata_simplify_sf %>% 
  left_join(spatial_division_urbain_rural,
            by = c("GMDNR" = "CODE_OFS"))

# Où sont les NAs? Les lacs et les communanz (ID = 2391, 5391)
geodata_na <- geodata_simplify_sf %>% filter(is.na(HR_GDETYP2012_L1_Name_fr)) %>%  print()
Simple feature collection with 25 features and 9 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: 2500610 ymin: 1064215 xmax: 2774076 ymax: 1297483
Projected CRS: CH1903+ / LV95
# A tibble: 25 × 10
   GMDNR GMDNAME               entity                      geom HR_GDETYP2012_L1
 * <dbl> <chr>                 <chr>         <MULTIPOLYGON [m]>            <dbl>
 1  2391 Staatswald Galm       COMMU… (((2581227 1196931, 2580…               NA
 2  5391 C'za Cadenazzo/Monte… COMMU… (((2723153 1111853, 2724…               NA
 3  9040 Greifensee            LAKE   (((2692711 1247539, 2694…               NA
 4  9050 Zürichsee             LAKE   (((2692980 1235162, 2693…               NA
 5  9073 Thunersee             LAKE   (((2627651 1170385, 2629…               NA
 6  9089 Brienzersee           LAKE   (((2634105 1171525, 2636…               NA
 7  9148 Bielersee / Lac de B… LAKE   (((2581863 1214635, 2580…               NA
 8  9151 Lac de Neuchâtel      LAKE   (((2568588 1206161, 2570…               NA
 9  9157 Baldeggersee          LAKE   (((2662046 1227079, 2660…               NA
10  9163 Sempachersee          LAKE   (((2653452 1223884, 2655…               NA
# ℹ 15 more rows
# ℹ 5 more variables: HR_GDETYP2012_L1_Name_fr <ord>, HR_GDETYP2012_L2 <dbl>,
#   HR_GDETYP2012_L2_Name_fr <ord>, HR_SPRGEB2020 <dbl>,
#   HR_SPRGEB2020_Name_fr <chr>
Code
# J'enlève les Communanz'
geodata_simplify_sf <- geodata_simplify_sf %>% 
  filter(!GMDNR %in% c(2391, 5391))

2.1.4 Process Geodata (ajout des votations)

Code
gd_votation_all <- geodata_simplify_sf %>% 
  left_join(pesticides_df)

gd_votation <- gd_votation_all %>% 
  select(GMDNR, GMDNAME, HR_GDETYP2012_L1_Name_fr, yes_pct, valid_votes, entity)

2.1.5 Process Geodata (split des communes et des lacs et sélection des variables)

Code
gd_votation_split <- split(gd_votation, gd_votation$entity)

gd_votation_commune <- gd_votation_split$COMMUNE %>% 
  select(-entity)

gd_votation_lac <- gd_votation_split$LAKE %>% 
  select(GMDNR, GMDNAME)

2.1.6 Export de la géométries

Code
# Spécifier les fichiesr de sorties
fichier1 <- "data_output/gd_votation_commune.geojson"
fichier2 <- "data_output/gd_votation_lac.geojson"

# Export des communes
gd_votation_commune %>%
  st_transform(4326) %>%
  write_sf(fichier1)

# Export des lacs
gd_votation_lac %>%
  st_transform(4326) %>%
  write_sf(fichier2) 


# -----
# COMMANDE POUR TRANSFORMER EN TOPOJSON EN UTILISANT MAPSHAPER NODE JS
# mapshaper_command <- "mapshaper"
# args <- c("data_output/gd_votation.geojson", "-o", "format=topojson", "data_output/gd_votation.topojson")

# Exécuter la commande
# output <- system2(mapshaper_command, args, stdout = TRUE, stderr = TRUE)
# cat(output, sep = "\n")

2.2 Combiner les fichiers avec CLI Mapshaper

Code
# Spécifier les chemins des fichiers GeoJSON

fichier_sortie <- "data_output/gd_votation_combined.topojson"

# Construire la commande Mapshaper avec l'ordre correct
commande <- paste("mapshaper -i", fichier1, fichier2, "combine-files -o", fichier_sortie)

# Exécuter la commande CLI depuis R
system(commande)

3 Storyboard

3.1 Carte choroplèthe

Code
library(RColorBrewer)
library(classInt)
library(tmap)

create_choro_map <- function(obj_sf, variable) {
  # Créer les intervalles de classe entre 0 et 100, par pas de 10
  breaks <- seq(0, 100, by = 10)
  
  # Obtenir la palette de couleurs PiYG avec 10 classes
  palette_couleurs <- brewer.pal(n = 10, name = "PiYG")
  
  # Classifier la variable selon les intervalles définis
  classes <- classIntervals(obj_sf[[variable]], n = 10, style = "fixed", fixedBreaks = breaks)
  
  # Enlever les NA
  obj_sf <- obj_sf %>% 
    filter(!is.na(yes_pct))
  
  # Créer la carte avec tmap
  map <- tm_shape(obj_sf) +
    tm_polygons(
      col = variable, 
      palette = palette_couleurs, 
      breaks = classes$brks,
      title = paste("Carte de", variable)
    )
  
  return(map)
}
Code
tmap_mode("plot")  # Pour une carte statique
tmap_mode("view")  # Pour une carte interactive

# Création de la map
create_choro_map(gd_votation, "yes_pct")

3.2 Carte en symboles proportionnels

Code
library(RColorBrewer)
library(classInt)
library(tmap)

create_choro_prop_map <- function(obj_sf, variable, voters) {
  # Créer les intervalles de classe entre 0 et 100, par pas de 10
  breaks <- seq(0, 100, by = 10)
  
  # Obtenir la palette de couleurs PiYG avec 10 classes
  palette_couleurs <- brewer.pal(n = 10, name = "PiYG")
  
  # Classifier la variable selon les intervalles définis
  classes <- classIntervals(obj_sf[[variable]], n = 10, style = "fixed", fixedBreaks = breaks)
  
  # Enlever les NA
  obj_sf <- obj_sf %>% 
    filter(!is.na(yes_pct))
  
  # Créer la carte avec tmap en ajoutant des cercles proportionnels
  map <- tm_shape(obj_sf) +
    tm_polygons(
      col = "lightgrey",
      alpha = 0.3
    ) +
    tm_bubbles(
      size = voters,               # Taille des cercles proportionnelle à la variable 'voters'
      col = variable,              # Couleur basée sur la même variable que la choroplèthe
      palette = palette_couleurs,  # Palette de couleurs
      breaks = classes$brks,       # Utiliser les mêmes coupures pour la classification
      border.col = "black",        # Bordure noire pour les cercles
      scale = 3,                 # Ajuster l'échelle des cercles pour une meilleure visualisation
      title.size = "Nombre d'électeurs",
      title.col = "Pourcentage de oui"
    )
  
  return(map)
}
Code
create_choro_prop_map(gd_votation, "yes_pct", "valid_votes")

3.3 Swarmbee

Code
make_swarmbee_plot <- function(df, col_type) {
  # Appliquer la transformation log10() directement aux données
  # df$voters_log <- log10(df$voters)
  
  df <- df %>% 
    filter(!is.na(HR_GDETYP2012_L1_Name_fr))
  # Convertir col_type en symbole pour être utilisé dans aes()
  col_type_sym <- rlang::ensym(col_type)
  
  ggplot(data = df, aes(x = !!col_type_sym, y = yes_pct, size = valid_votes, color = !!col_type_sym)) +
    geom_beeswarm(alpha = 0.7) +
    theme_minimal() +
    labs(
      title = "Répartition des votes pour l'initiative «Pour une eau potable propre et une alimentation saine»",
      x = "Type de commune",
      y = "Pourcentage de 'Oui'",
      size = "Log du nombre d'électeurs"
    ) +
    coord_flip() +
    theme(legend.position = "none")
}

# Exemple d'utilisation
# make_swarmbee_plot(rothenthurm_sf, "HR_GDETYP2012_L1_Name_fr")
Code
make_swarmbee_plot(gd_votation, HR_GDETYP2012_L1_Name_fr)

Code
make_swarmbee_plot(gd_votation_all, HR_GDETYP2012_L2_Name_fr)